package de.dhbw.karlsruhe.picsim.model.decode;

import de.dhbw.karlsruhe.picsim.model.commands.PicInstruction;
import de.dhbw.karlsruhe.picsim.model.memory.OpCode;
import de.dhbw.karlsruhe.picsim.util.Bits;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 12, 2010
 * Time: 4:08:02 PM
 */

/**
 * Entscheidet welcher Dekoder ausgeführt wird
 */
public final class DecoderImpl implements Decoder {
    private static final Log log = LogFactory.getLog(DecoderImpl.class);

    @NotNull
    @Override
    public PicInstruction decode(@NotNull final OpCode opCode) {
        log.debug("The Opcode " + opCode + " is getting decoded");
        final Bits bits = opCode.getValue();
        if (bits.isSet(13) && !bits.isSet(12)) {
            return new LiteralDecoder10().decode(opCode);
        } else if (!bits.isSet(13) && !bits.isSet(12)) {
            return isByteOrientated(bits)
                   ? new ByteOrientatedDecoder().decode(opCode)
                   : new LiteralDecoder00().decode(opCode);
        } else if (!bits.isSet(13) && bits.isSet(12)) {
            return new BitDecoder().decode(opCode);
        }
        return new LiteralDecoder11().decode(opCode);


    }

    private boolean isByteOrientated(final Bits bits) {
        return bits.isSet(11) || bits.isSet(10) || bits.isSet(9) || bits.isSet(8) || bits.isSet(7) || couldBeNoOp(bits);
    }

    private boolean couldBeNoOp(final Bits bits) {
        return (!bits.isSet(3)) && !bits.isSet(2) && !bits.isSet(1) && !bits.isSet(0);
    }
}
